<?php
/**
 * Created by PhpStorm.
 * User: fengyan
 * Date: 18-1-4
 * Time: 下午3:09
 */

namespace App\Repositories\Addons\Uploads\Drive;


use App\Repositories\Addons\Uploads\ReturnFileInfo;
use App\Repositories\Addons\Uploads\ReturnMsg;
use App\Repositories\Addons\Uploads\UploadsInter;
use Upload\File;
use Upload\Storage\FileSystem;

class LocalDrive extends BaseDrive implements UploadsInter
{
    /**
     * 新的文件路径以及名称
     * @var
     */
    protected $newFilePathName;


    /**
     * 获取上传配置
     * @return mixed
     */
    public function config()
    {
        $plugins = isset($this->config['plugins']) ? $this->config['plugins'] : 'ueditor';
        $config = [];

        switch ($plugins) {
            default :
                foreach ($this->config as $key=>$value) {
                    if (!is_array($value) || $key == 'actionPrefixKeyList') {
                        continue;
                    }
                    foreach ($value as $k=>$val) {
                        $config[$key.ucfirst($k)] = $val;
                    }
                }
                break;
        }

        $this->result = new ReturnMsg(0, '', $config);

        return $this;
    }

    /**
     * 获取文件链接地址
     * @param $filePathName
     * @return string
     */
    public function getLinks($filePathName)
    {
        return $this->config['links'] . $filePathName;
    }

    /**
     * 上传
     */
    public function upload()
    {
        $newFilePathName = $this->getFullName($_FILES[$this->fieldName]['name']);

        $directory = $this->getBasePath() . dirname($newFilePathName);

        if (!is_dir($directory)) {
            @mkdir($directory,0777,true);
        }
        
        $storage = new FileSystem($directory);

        $file = new File($this->fieldName, $storage);

        //  上传验证
        $validateData = [];

        if (isset($this->config['allowMimetype']) && !empty($this->config['allowMimetype'])) {
            $validateData[] = new \Upload\Validation\Mimetype($this->config['allowMimetype']);
        }

        if (isset($this->config['maxSize']) && !empty($this->config['maxSize'])) {
            $maxSize = $this->config['maxSize'] / (1024 * 1000) . 'M';

            $validateData[] = new \Upload\Validation\Size($maxSize);
        }

        if (!empty($validateData)) {
            $file->addValidations($validateData);
        }

        $newFileName = basename($newFilePathName);

        $data = [
            'original'   => $file->getNameWithExtension(),
            'title'      => $newFileName,
            'path'       => $newFilePathName,
            'extension'  => $file->getExtension(),
            'mime'       => $file->getMimetype(),
            'size'       => $file->getSize(),
            'md5'        => $file->getMd5(),
            'dimensions' => $file->getDimensions(),
            'links'      => $this->getLinks($newFilePathName),
        ];

        try {
            $file->upload($newFileName);

            $this->result = new ReturnMsg(0, '',  new ReturnFileInfo($data));

        } catch (\Exception $e) {
            $this->result = new ReturnMsg(-1, $file->getErrors(), []);
        }

        return $this;
    }

    /**
     * 图片上传
     * @return mixed
     */
    public function uploadImage()
    {
        return $this->upload();
    }

    /**
     * 上传涂鸦
     * @return mixed
     */
    public function uploadScrawl()
    {
        // TODO: Implement uploadScrawl() method.
    }

    /**
     * 上传视频
     * @return mixed
     */
    public function uploadVideo()
    {
        // TODO: Implement uploadVideo() method.
    }

    /**
     * 上传文件
     * @return mixed
     */
    public function uploadFile()
    {
        // TODO: Implement uploadFile() method.
    }

    /**
     * 列出图片
     * @return mixed
     */
    public function listImage($start, $size)
    {
        return $this->getLists($start, $size);
    }

    /**
     * 列出文件
     * @return mixed
     */
    public function listFile($start, $size)
    {
        return $this->getLists($start, $size);
    }

    private function getLists($start, $size)
    {
        $allowFiles = substr(str_replace(".", "|", join("", $this->config['allowFiles'])), 1);
        $path = $this->basePath . $this->config['listPath'];
        $files = $this->getFileLists($path, $allowFiles);

        if (!count($files)) {
            $this->result = new ReturnMsg(-1, '', [
                "state" => "no match file",
                "list" => array(),
                "start" => $start,
                "total" => count($files)
            ]);

            return $this;
        }

        $end = $start + $size;

        /* 获取指定范围的列表 */
        $len = count($files);
        for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--){
            $list[] = $files[$i];
        }

        /* 返回数据 */
        $this->result = new ReturnMsg(0 , '', [
            "state" => "SUCCESS",
            "list"  => $list,
            "start" => $start,
            "total" => count($files)
        ]);

        return $this;
    }

    /**
     * 遍历获取目录下的指定类型的文件
     * @param $path
     * @param $allowFiles
     * @param array $files
     * @return array|null
     */
    private function getFileLists($path, $allowFiles, &$files = [])
    {
        if (!is_dir($path)) return null;
        if(substr($path, strlen($path) - 1) != '/') $path .= '/';
        $handle = opendir($path);
        while (false !== ($file = readdir($handle))) {
            if ($file != '.' && $file != '..') {
                $path2 = $path . $file;

                if (is_dir($path2)) {
                    $this->getFileLists($path2, $allowFiles, $files);
                } else {
                    if (preg_match("/\.(".$allowFiles.")$/i", $file)) {
                        $files[] = array(
                            'url'=> $this->getLinks(str_replace($this->basePath, '', $path2)),
                            'mtime'=> filemtime($path2)
                        );
                    }
                }
            }
        }
        return $files;
    }

    /**
     * 抓取远程文件
     * @return mixed
     */
    public function catchImage()
    {
        // TODO: Implement catchImage() method.
    }
}